#include "DotProcessor.h"
#include "FibonacciHeap.h"
#include "BinaryHeap.h"
#include "NodeList.h"
#include "Dijkstra.h"
#include "HeapTester.h"
#include "DijkstraTester.h"

#include <iostream>
#ifdef linux

#else
  #include <conio.h>
#endif

using namespace std;

class Element : public algo::NodeListElement<Element> {};

int main(int argv, char* argc[]) {
  /*
  algo::BinaryHeap<int> bheap;

  bheap.insert(5);
  bheap.insert(3);
  bheap.insert(2);
  bheap.insert(1);
  algo::BinaryHeapNode<int> *bn7 = bheap.insert(7);

  std::cout << "Init done" << endl;

  bheap.decreaseKey(bn7, 4);

  std::cout << "Test af BinaryHeap" << endl;
  std::cout << bheap.deleteMin() << endl;
  std::cout << bheap.deleteMin() << endl;
  std::cout << bheap.deleteMin() << endl;
  std::cout << bheap.deleteMin() << endl;
  std::cout << bheap.deleteMin() << endl;

  algo::FibonacciHeap<int> heap;
  algo::FibonacciHeapNode<int> *n7 = heap.insert(7);
  algo::FibonacciHeapNode<int> *n3 = heap.insert(3);
  algo::FibonacciHeapNode<int> *n5 = heap.insert(5);
  algo::FibonacciHeapNode<int> *n1 = heap.insert(1);
  algo::FibonacciHeapNode<int> *n8 = heap.insert(8);

  heap.deleteMin();
//  DotProcessor().show(heap.dotString());
  heap.decreaseKey(n8, 2);
//  DotProcessor().show(heap.dotString());
  heap.decreaseKey(n7, 1);
//  DotProcessor().show(heap.dotString());
  heap.decreaseKey(n5, 0);
//  DotProcessor().show(heap.dotString());
*/

  
  algo::DijkstraNode d1;
  algo::DijkstraNode d2;
  algo::DijkstraNode d3;
  algo::DijkstraNode d4;

  d1.addEdge(&d2, 1);
  d1.addEdge(&d3, 3);
  d2.addEdge(&d4, 4);
  d2.addEdge(&d3, 1);
  d3.addEdge(&d4, 1);

  std::vector<algo::DijkstraNode*> nodes;
  nodes.push_back(&d1);
  nodes.push_back(&d2);
  nodes.push_back(&d3);
  nodes.push_back(&d4);
/*
  algo::Dijkstra dijkstra(new algo::BinaryHeap<algo::DijkstraHeapNode>(), &nodes);
  dijkstra.run(&d1);
  cout << "we are soooo far away: " << d4.getDistance() << endl;
*/

//  cout << "size: " << sizeof(algo::FibonacciHeapNode<int*>) << endl;


  HeapTester tester;
//  tester.testFolder("../heap-tests/");
//  tester.timeFolder("../heap-tests/");

  DijkstraTester dtester;
//  dtester.testFile("../dijkstra-tests/decrease_key5.dijkstra");
//  dtester.timeFile("../dijkstra-tests/decrease_key5.dijkstra");
  dtester.timeFile(argc[1]);
// dtester.testFolder("../dijkstra-tests/");
//  dtester.timeFolder("../dijkstra-tests/");
//  tester.timeFile("../heap-tests/long_list_reverse.heap");

/*
  std::vector<int> list;
  for (int i = 0; i < 100; i++)
    list.push_back(i);

  for (int i = 0; i < 100; i++) {
    std::swap(list[i], list[rand() % 100]);
  }

  for (int i = 0; i < 100; i++) {
    heap.insert(list[i]);
  }

  for (int i = 0; i < 100; i++) {
    DotProcessor().show(heap.dotString());
    heap.deleteMin();
    cout << heap.getMin()->getKey() << endl;
  }
  */

 /* {
    algo::NodeList<Element> list;
    Element *e = list.push_front(new Element());
    list.push_front(new Element());
    list.push_front(new Element());
    DotProcessor().show(list.dotString());
    list.push_front(new Element());
    DotProcessor().show(list.dotString());
    list.push_front(new Element());
    DotProcessor().show(list.dotString());
    list.push_front(new Element());
    DotProcessor().show(list.dotString());
    list.push_front(new Element());
    DotProcessor().show(list.dotString());

    list.remove(e);

  }*/
#ifdef linux
  // no need to sleep in linux ^^
#else
  _getch();
#endif
}
